package com.kreao.korean.service;

import com.kreao.korean.dto.WordRequest;
import com.kreao.korean.dto.WordResponse;
import com.kreao.korean.entity.User;
import com.kreao.korean.entity.Word;
import com.kreao.korean.exception.ResourceNotFoundException;
import com.kreao.korean.mapper.WordMapper;
import com.kreao.korean.repository.UserRepository;
import com.kreao.korean.repository.WordRepository;
import com.kreao.korean.service.interfaces.WordService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service("wordServiceImpl")
@RequiredArgsConstructor
@Transactional
public class WordServiceImpl implements WordService {
    
    private final WordRepository wordRepository;
    private final UserRepository userRepository;
    private final WordMapper wordMapper;
    
    public WordResponse createWord(WordRequest request, Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new ResourceNotFoundException("User", "id", userId));
        
        Word word = wordMapper.toEntity(request);
        word.setUser(user);
        
        Word savedWord = wordRepository.save(word);
        
        // 更新用户单词总数
        user.setTotalWords(user.getTotalWords() + 1);
        userRepository.save(user);
        
        return wordMapper.toResponse(savedWord);
    }
    
    public WordResponse updateWord(Long wordId, WordRequest request, Long userId) {
        Word word = wordRepository.findById(wordId)
            .orElseThrow(() -> new RuntimeException("单词不存在"));
        
        if (!word.getUser().getId().equals(userId)) {
            throw new RuntimeException("无权限修改此单词");
        }
        
        word.setKorean(request.getKorean());
        word.setChinese(request.getChinese());
        word.setPronunciation(request.getPronunciation());
        word.setRomanization(request.getRomanization());
        word.setExamples(request.getExamples());
        word.setNotes(request.getNotes());
        word.setCategory(request.getCategory());
        word.setLevel(request.getLevel());
        word.setWordType(request.getWordType());
        word.setIsFavorite(request.getIsFavorite());
        word.setIsPublic(request.getIsPublic());
        
        Word savedWord = wordRepository.save(word);
        return WordResponse.fromEntity(savedWord);
    }
    
    public void deleteWord(Long wordId, Long userId) {
        Word word = wordRepository.findById(wordId)
            .orElseThrow(() -> new RuntimeException("单词不存在"));
        
        if (!word.getUser().getId().equals(userId)) {
            throw new RuntimeException("无权限删除此单词");
        }
        
        wordRepository.delete(word);
        
        // 更新用户单词总数
        User user = word.getUser();
        user.setTotalWords(Math.max(0, user.getTotalWords() - 1));
        userRepository.save(user);
    }
    
    public WordResponse getWord(Long wordId, Long userId) {
        Word word = wordRepository.findById(wordId)
            .orElseThrow(() -> new RuntimeException("单词不存在"));
        
        if (!word.getUser().getId().equals(userId) && !word.getIsPublic()) {
            throw new RuntimeException("无权限查看此单词");
        }
        
        return WordResponse.fromEntity(word);
    }
    
    public Page<WordResponse> getUserWords(Long userId, Pageable pageable) {
        Page<Word> words = wordRepository.findByUserId(userId, pageable);
        return words.map(WordResponse::fromEntity);
    }
    
    public Page<WordResponse> searchWords(Long userId, String keyword, Pageable pageable) {
        Page<Word> words = wordRepository.findByUserIdAndKoreanContainingOrChineseContaining(
            userId, keyword, keyword, pageable);
        return words.map(WordResponse::fromEntity);
    }
    
    public Page<WordResponse> getWordsByCategory(Long userId, Word.WordCategory category, Pageable pageable) {
        Page<Word> words = wordRepository.findByUserIdAndCategory(userId, category, pageable);
        return words.map(WordResponse::fromEntity);
    }
    
    public Page<WordResponse> getFavoriteWords(Long userId, Pageable pageable) {
        Page<Word> words = wordRepository.findByUserIdAndIsFavorite(userId, true, pageable);
        return words.map(WordResponse::fromEntity);
    }
    
    public List<WordResponse> getWordsForReview(Long userId) {
        List<Word> words = wordRepository.findByUserIdAndNextReviewTimeBefore(userId, LocalDateTime.now());
        return words.stream().map(WordResponse::fromEntity).collect(Collectors.toList());
    }
    
    public List<WordResponse> getWordsNeedReview(Long userId, Double accuracy) {
        List<Word> words = wordRepository.findWordsNeedReview(userId, accuracy);
        return words.stream().map(WordResponse::fromEntity).collect(Collectors.toList());
    }
    
    public WordResponse toggleFavorite(Long wordId, Long userId) {
        Word word = wordRepository.findById(wordId)
            .orElseThrow(() -> new RuntimeException("单词不存在"));
        
        if (!word.getUser().getId().equals(userId)) {
            throw new RuntimeException("无权限修改此单词");
        }
        
        word.setIsFavorite(!word.getIsFavorite());
        Word savedWord = wordRepository.save(word);
        return WordResponse.fromEntity(savedWord);
    }
    
    @Override
    public List<WordResponse> importWords(List<WordRequest> wordRequests, Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        List<Word> words = wordRequests.stream()
            .map(request -> {
                Word word = new Word();
                word.setKorean(request.getKorean());
                word.setChinese(request.getChinese());
                word.setPronunciation(request.getPronunciation());
                word.setRomanization(request.getRomanization());
                word.setExamples(request.getExamples());
                word.setNotes(request.getNotes());
                word.setCategory(request.getCategory());
                word.setLevel(request.getLevel());
                word.setWordType(request.getWordType());
                word.setIsFavorite(request.getIsFavorite());
                word.setIsPublic(request.getIsPublic());
                word.setUser(user);
                word.setNextReviewTime(LocalDateTime.now().plusDays(1));
                return word;
            })
            .toList();
        
        List<Word> savedWords = wordRepository.saveAll(words);
        
        // 更新用户单词总数
        user.setTotalWords(user.getTotalWords() + savedWords.size());
        userRepository.save(user);
        
        return savedWords.stream()
            .map(WordResponse::fromEntity)
            .collect(Collectors.toList());
    }
    
    @Override
    public WordStatistics getWordStatistics(Long userId) {
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        
        Long totalWords = wordRepository.countByUserId(userId);
        Long favoriteWords = wordRepository.findByUserIdAndIsFavorite(userId, true, null).getTotalElements();
        Long reviewWords = wordRepository.getTotalReviewCountByUserId(userId);
        Long todayStudyWords = wordRepository.countByUserIdAndCreatedAtAfter(userId, startOfDay);
        
        return new WordStatistics(
            totalWords,
            favoriteWords,
            reviewWords != null ? reviewWords : 0L,
            todayStudyWords
        );
    }
} 